package com.zhanghu.backendZray.websocket;

import com.zhanghu.backendZray.pojo.dto.UserTokenInfo;
import com.zhanghu.backendZray.service.AlbumCollectionService;
import com.zhanghu.backendZray.service.UserOnlineTokenService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.zhanghu.backendZray.constants.CommonConstant.PING;

/**
 * @author ZhangDong
 * @date 2024/12/26 16:27
 */
@Slf4j
@Component
@ServerEndpoint(value = "/wsConnect/{token}/{userId}")
public class WebsocketServer {

    private static final Map<Integer, Session> SESSION_MAP = new ConcurrentHashMap<>();
    private static UserOnlineTokenService userOnlineTokenService;
    private static AlbumCollectionService albumCollectionService;

    public static boolean sessionOpen() {
        Collection<Session> values = SESSION_MAP.values();
        for (Session value : values) {
            if (value.isOpen()) {
                return true;
            }
        }
        return false;
    }


    /**
     * 发送消息
     */
    @SneakyThrows
    public static boolean sendMessage(Integer userId, String message) {
        Session session = SESSION_MAP.get(userId);
        if (session != null && session.isOpen()) {
            session.getBasicRemote().sendText(message);
//            session.getAsyncRemote().sendText(message);
            return true;
        } else {
            return false;
        }
    }

    @Autowired
    public void setUserOnlineTokenService(UserOnlineTokenService userOnlineTokenService) {
        WebsocketServer.userOnlineTokenService = userOnlineTokenService;
    }

    @Autowired
    public void setAlbumCollectionService(AlbumCollectionService albumCollectionService) {
        WebsocketServer.albumCollectionService = albumCollectionService;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam(value = "userId") Integer userId, @PathParam(value = "token") String token, Session session) {
        log.info("用户连接成功:" + userId);
        // 登录状态校验
        if (!checkLoginStatus(token)) {
            log.info("非登录状态下websocket连接, pass...");
            return;
        }
        SESSION_MAP.put(userId, session);

        // 一连接，即推送代办消息
        albumCollectionService.pendingTaskMesPush(userId);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam(value = "userId") Integer userId, @PathParam(value = "token") String token, Session session1) throws IOException {
        // 登录状态校验
        if (!checkLoginStatus(token)) {
            log.info("非登录状态下websocket连接, pass...");
            return;
        }
        Session session = SESSION_MAP.get(userId);
        if (session != null) {
            if (session.isOpen()) {
                session.close();
            }
            SESSION_MAP.remove(userId);
        }
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(@PathParam(value = "userId") Integer userId, @PathParam(value = "token") String token, String message, Session session) {
        // 登录状态校验
        if (!checkLoginStatus(token)) {
            log.info("非登录状态下websocket连接, pass...");
            return;
        }
        log.info("收到来自客户端的消息:" + message);
        // 心跳消息处理
        if (PING.equals(message)) {
            userOnlineTokenService.updateUserStatusAndTokenRenewal(userId);
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("websocket连接出错：" + error.getMessage());
    }

    /**
     * 登录状态校验
     */
    private boolean checkLoginStatus(String token) {
        UserTokenInfo userTokenInfo = userOnlineTokenService.getUserTokenInfoByToken(token);
        return userTokenInfo != null;
    }

}


